package org.dppc.fine4j.proxychain.support;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.dppc.fine4j.proxychain.MethodProxy;
import org.dppc.fine4j.proxychain.ProxyHandler;

/**
 * ProxyHandler 模板类
 * 
 * @author maomh
 *
 */
public abstract class AbstractProxyHandler implements ProxyHandler {
	/**
	 * 代理对象
	 */
	protected Object proxy;
	
	/**
	 * 代理目标对象
	 */
	protected Object target;
	
	/**
	 * 方法代理链
	 */
	protected List<MethodProxy> methodProxies =new ArrayList<MethodProxy>();
	
	
	/**
	 * 检查类型的方法 由子类实现
	 * 
	 * @param object
	 */
	protected abstract boolean checkType(Object object);
	
	// 检查参数 proxy/target
	private void checkObject(Object object) throws TypeErrorException {
		if (object == null) {
			throw new NullPointerException("参数不能为 null！");
		}
		if (!checkType(object)) {
			throw new TypeErrorException(getTarget().getClass());
		}
	}
	
	
	/**
	 * 设置句柄持有的代理对象
	 * 
	 * @param proxy
	 * @throws TypeErrorException 
	 */
	public void setProxy(Object proxy) throws TypeErrorException {
		this.proxy =proxy;
	}

	
	@SuppressWarnings("unchecked")
	@Override
	public <T> T getProxy() {
		return (T) proxy;
	}

	
	@Override
	public void setTarget(Object target) throws TypeErrorException {
		this.checkObject(target);
		this.target =target;
	}

	
	@SuppressWarnings("unchecked")
	@Override
	public <T> T getTarget() {
		return (T) target;
	}


	@Override
	public void addMethodProxy(Collection<MethodProxy> methodProxies) {
		if (methodProxies != null) {
			this.methodProxies.addAll(methodProxies);
		}
	}

	@Override
	public void addMethodProxy(MethodProxy... methodProxies) {
		if (methodProxies != null && methodProxies.length >0) {
			this.methodProxies.addAll(Arrays.asList(methodProxies));
		}
	}

	@Override
	public void clearAllMethodProxy() {
		this.methodProxies.clear();
	}

	@Override
	public MethodProxy[] getAllMethodProxy() {
		MethodProxy[] methodProxies =new MethodProxy[this.methodProxies.size()];
		this.methodProxies.toArray(methodProxies);
		return methodProxies;
	}

	@Override
	public void sortMethodProxies(Comparator<MethodProxy> comparator) {
		Collections.sort(this.methodProxies, comparator);
	}
}
